package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private VodService vodService;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;


    //保存声音
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
        try {
            //track_info track_stat album_info
            //1.track_info
            TrackInfo trackInfo = new TrackInfo();
            //有相同的属性直接进行属性拷贝
            BeanUtils.copyProperties(trackInfoVo, trackInfo);
            //赋值用户id
            trackInfo.setUserId(userId);
            //order_num
            //两种方式:
            //方式一:查询当前专辑对应的声音集数+1
            //方式二:查询专辑包含声音总数+1
            AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
            trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() + 1);
            //处理流媒体的数据,  时长,类型这些数据页面没有传递?怎么查?根据fileId查询流媒体数据,然后赋值
            //所以要调用云点播的API
            //https://console.cloud.tencent.com/api/explorer?Product=vod&Version=2018-07-17&Action=DescribeMediaInfos
            //通过上述地址分析,我们需要传递MediaFileId()
            TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
            //赋值
            trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
            trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
            trackInfo.setMediaSize(trackMediaInfoVo.getSize());
            trackInfo.setMediaType(trackMediaInfoVo.getType());
            //保存声音结束
            trackInfoMapper.insert(trackInfo);

            //2.track_stat
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);

            //album_info只需要更新数据就行
            albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
            //更新操作,albumInfo在上边已经根据id查了
            albumInfoMapper.updateById(albumInfo);
        } catch (BeansException e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }


    }

    //保存声音统计数据
    //事务在private下不会生效
    //事务实现的本质:反射+代理 如果是private就自己内部,不能代理
    public void saveTrackStat(Long trackId, String statPlay) {
        TrackStat trackStat = new TrackStat();
        //赋值
        trackStat.setTrackId(trackId);
        trackStat.setStatType(statPlay);
        trackStat.setStatNum(new Random().nextInt(10000));
        //保存数据
        trackStatMapper.insert(trackStat);

    }

    //查询声音
    @Override
    public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> trackListVoPage, TrackInfoQuery trackInfoQuery) {
        //调用mapper层方法
        return trackInfoMapper.selectUserTrackPage(trackListVoPage, trackInfoQuery);

    }

    //根据声音Id删除声音数据
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeTrackInfo(Long trackId) {
        //获取当前声音对象
        TrackInfo trackInfo = this.getById(trackId);
        //track_info track_stat album_info
        //删除track_info的数据
        trackInfoMapper.deleteById(trackId);
        //删除track_stat
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, trackId));
        //更新album_info中的声音总数include_track_count
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        //删除一条记录并且重新赋值
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        //保存更新
        albumInfoMapper.updateById(albumInfo);
        //删除完数据之后,声音在专辑中的排序也会发生变化,重新更新order_num
        //update track_info set order_num=order_num-1 where album_id=专辑id and order_num>当前顺序 and is_deleted=0
        trackInfoMapper.updateOrderNum(trackInfo.getAlbumId(), trackInfo.getOrderNum());
        //删除云点播中没有用的声音记录
        vodService.deleteMediaFile(trackInfo.getMediaFileId());
    }

    //修改声音
    @Override
    public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
        TrackInfo trackInfo = this.getById(trackId);
        //先获取原始的文件id
        String originMediaFileId = trackInfo.getMediaFileId();
        //属性赋值,进行拷贝
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //判断声音是否被修改,此时就需要比较MediaFileId,相等则没有修改,不相等代表修改
        if (!originMediaFileId.equals(trackInfoVo.getMediaFileId())) {
            //不相等,代表修改声音
            TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfo.getMediaFileId());
            //重新给流媒体数据赋值
            trackInfo.setMediaType(mediaInfo.getType());
            trackInfo.setMediaSize(mediaInfo.getSize());
            trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
            trackInfo.setMediaDuration(mediaInfo.getDuration());
            //如果原来的不要了的话,可以删除
            vodService.deleteMediaFile(originMediaFileId);
        }
        //更新数据
        this.updateById(trackInfo);
    }

    /**
     * 根据专辑ID获取专辑声音列表
     * @param albumTrackListVoPage
     * @param albumId
     * @param userId
     * @return
     */
    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> albumTrackListVoPage, Long albumId, Long userId) {
        //1.先根据专辑Id获取声音列表
        IPage<AlbumTrackListVo> albumTrackListVoIPage = trackInfoMapper.selectAlbumTrackList(albumTrackListVoPage, albumId);
        /*2.判断用户是否登录
            2.1 判断专辑类型

            2.2除用户已购买的声音Id
        */
        //获取专辑对象,用于查询专辑类型
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        if (null == userId) {
            //此时说明,用户没有登录,那么专辑类型若为付费(vip或者付费),除免费试听声音都需要付费
            if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
                //免费试听集数
                Integer tracksForFree = albumInfo.getTracksForFree();
                //除免费试听集数的声音都需要付费
                albumTrackListVoIPage.getRecords().stream()
                        .filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFree)
                        .forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
            }
        } else {
            //用户登录,此时需要获取用户信息
            Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
            Assert.notNull(userInfoVoResult, "查询用户信息失败");
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            Assert.notNull(userInfoVo, "查询用户信息失败");
            //先声明一个变量,用于记录是否需要付费---false代表免费
            boolean isPaid = false;
            //判断专辑的类型:vip免费
            if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())) {
                //此时,若用户不是vip,或者vip已经过期都需要付费
                if ((userInfoVo.getIsVip() == 1 && userInfoVo.getVipExpireTime().before(new Date()))
                        || userInfoVo.getIsVip() == 0) {
                    //付费
                    isPaid = true;
                }
            } else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
                //判断专辑的类型:付费
                //此时必须付费
                isPaid = true;
            }
            //最后一种专辑的类型:免费,此时不需要进行其他操作,因为本来变量就是false,代表免费

            //判断需要付费的情况
            if (isPaid) {
                //  远程调用，需要知道用户购买了哪些声音; 专辑Id; 付费声音列表;userId从本地线程中获取;
                List<AlbumTrackListVo> albumTrackListVoList = albumTrackListVoIPage.getRecords().stream()
                        .filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
                        .collect(Collectors.toList());
                //  获取付费声音Id
                List<Long> trackIdList = albumTrackListVoList.stream()
                        .map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
                //	获取用户购买的声音列表; 购买了,将购买的声音Id与状态存储到map集合中
                Result<Map<Long, Integer>> mapResult = userInfoFeignClient.userIsPaidTrack(albumId, trackIdList);
                Assert.notNull(mapResult, "查询用户购买声音失败");
                Map<Long, Integer> map = mapResult.getData();
                Assert.notNull(map, "查询用户购买声音失败");
                //map.put(trackId,1)-买过   map.put(trackId,0)-未买过
                for (AlbumTrackListVo albumTrackListVo : albumTrackListVoList) {
                    albumTrackListVo.setIsShowPaidMark(map.get(albumTrackListVo.getTrackId()) == 0);
                }
            }
        }
        //返回数据
        return albumTrackListVoIPage;
    }

    /**
     * 修改声音播放统计数据
     * @param trackStatMqVo
     */
    @Override
    public void updateTrackStat(TrackStatMqVo trackStatMqVo) {
        //更新声音的播放量
        ///判断是否属于播放量
        if (SystemConstant.TRACK_STAT_PLAY.equals(trackStatMqVo.getStatType())){
            //调用更新方法
            trackInfoMapper.updateTrackStat(trackStatMqVo.getCount(),trackStatMqVo.getTrackId(),trackStatMqVo.getStatType());
            //更新专辑的播放量
            albumInfoMapper.updateAlbumStat(trackStatMqVo.getCount(),trackStatMqVo.getAlbumId(),SystemConstant.ALBUM_STAT_PLAY);
        }

    }
}
